package com.example.javapoet.demo.basic;

import com.squareup.javapoet.*;

import javax.lang.model.element.Modifier;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * JavaPoet基础示例 - 生成注解类型
 */
public class BasicAnnotationGeneration {

    public static void main(String[] args) {
        // 生成一个简单的标记注解
        generateSimpleMarkerAnnotation();
        
        // 生成一个带属性的注解
        generateAnnotationWithAttributes();
        
        // 生成一个复杂的注解
        generateComplexAnnotation();
    }

    /**
     * 生成一个简单的标记注解
     */
    public static void generateSimpleMarkerAnnotation() {
        // 创建注解
        TypeSpec debugAnnotation = TypeSpec.annotationBuilder("Debug")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(Retention.class)
                        .addMember("value", "$T.$L", RetentionPolicy.class, RetentionPolicy.RUNTIME.name())
                        .build())
                .addAnnotation(AnnotationSpec.builder(Target.class)
                        .addMember("value", "{$T.$L, $T.$L}", 
                                ElementType.class, ElementType.METHOD.name(),
                                ElementType.class, ElementType.TYPE.name())
                        .build())
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.annotation", debugAnnotation)
                .build();

        try {
            // 输出到控制台
            System.out.println("生成Debug注解:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成Debug.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一个带属性的注解
     */
    public static void generateAnnotationWithAttributes() {
        // 创建注解
        TypeSpec apiAnnotation = TypeSpec.annotationBuilder("API")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(Retention.class)
                        .addMember("value", "$T.$L", RetentionPolicy.class, RetentionPolicy.RUNTIME.name())
                        .build())
                .addAnnotation(AnnotationSpec.builder(Target.class)
                        .addMember("value", "$T.$L", ElementType.class, ElementType.TYPE.name())
                        .build())
                // 添加属性（在注解中是方法）
                .addMethod(MethodSpec.methodBuilder("name")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(String.class)
                        .defaultValue("$S", "")
                        .build())
                .addMethod(MethodSpec.methodBuilder("version")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(String.class)
                        .defaultValue("$S", "1.0")
                        .build())
                .addMethod(MethodSpec.methodBuilder("description")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(String.class)
                        .defaultValue("$S", "API Description")
                        .build())
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.annotation", apiAnnotation)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成API注解:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成API.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一个复杂的注解
     */
    public static void generateComplexAnnotation() {
        // 创建一个枚举作为注解的属性类型
        TypeSpec httpMethodEnum = TypeSpec.enumBuilder("HttpMethod")
                .addEnumConstant("GET")
                .addEnumConstant("POST")
                .addEnumConstant("PUT")
                .addEnumConstant("DELETE")
                .addEnumConstant("PATCH")
                .build();
        
        // 创建注解
        TypeSpec endpointAnnotation = TypeSpec.annotationBuilder("Endpoint")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(Retention.class)
                        .addMember("value", "$T.$L", RetentionPolicy.class, RetentionPolicy.RUNTIME.name())
                        .build())
                .addAnnotation(AnnotationSpec.builder(Target.class)
                        .addMember("value", "{$T.$L, $T.$L}", 
                                ElementType.class, ElementType.METHOD.name(),
                                ElementType.class, ElementType.TYPE.name())
                        .build())
                // 添加嵌套的枚举类型
                .addType(httpMethodEnum)
                // 添加属性（在注解中是方法）
                .addMethod(MethodSpec.methodBuilder("path")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(String.class)
                        .build())
                .addMethod(MethodSpec.methodBuilder("method")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(ClassName.get("com.example.annotation", "Endpoint", "HttpMethod"))
                        .defaultValue("$T.$L", 
                                ClassName.get("com.example.annotation", "Endpoint", "HttpMethod"),
                                "GET")
                        .build())
                .addMethod(MethodSpec.methodBuilder("produces")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(String[].class)
                        .defaultValue("{$S, $S}", "application/json", "application/xml")
                        .build())
                .addMethod(MethodSpec.methodBuilder("consumes")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(String[].class)
                        .defaultValue("{$S}", "application/json")
                        .build())
                .addMethod(MethodSpec.methodBuilder("secured")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(boolean.class)
                        .defaultValue("$L", false)
                        .build())
                .addMethod(MethodSpec.methodBuilder("roles")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(String[].class)
                        .defaultValue("{}")
                        .build())
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.annotation", endpointAnnotation)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成Endpoint注解:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成Endpoint.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}